#include "Graphics.h"
#include "Header.h"
#include "Utils.h"
#include "Rect.h"
#include "Texture.h"

Graphics* Graphics::instance=0;

RenderInfo::RenderInfo(Texture* texture, Rect* src, Rect* des, float angle, float alpha, float deep)
{
	this->texture = texture;
	this->src = new Rect(src);
	this->des = new Rect(des);
	this->alpha = alpha;
	this->deep = deep;
	this->angle = angle;
}

RenderInfo::~RenderInfo()
{
	DELETE_SAFELY(src);
	DELETE_SAFELY(des);
};

Graphics::Graphics()
{
	width = height = 0;
}
Graphics* Graphics::GetInstance()
{
	if(instance == 0)
	{
		PRINT("Init Graphics\n");
		instance = new Graphics();
	}
	return instance;
}

void Graphics::Init(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
#ifdef WIN32
	glOrtho(0.0f, width, height, 0.f, -100.0f, 100.0f);
#elif ANDROID
	glOrthof(0.0f, width, height, 0.f, -100.0f, 100.0f);
#endif

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_TEXTURE_2D);
	glClearColor(1,1,1,1);
	glDisable(GL_CULL_FACE);

	glMatrixMode(GL_MODELVIEW);
}

void Graphics::RenderTexture(Texture* texture, Rect* src, Rect* des, float angle, float alpha, float deep)
{
	RenderInfo *renderInfo = new RenderInfo(texture, src, des, angle, alpha, deep);
	renderInfos.push_back(renderInfo);
}

Graphics::~Graphics()
{
}

void Graphics::RenderATexture(RenderInfo* renderInfo)
{
	Texture* texture = renderInfo->texture;
	Rect* src = renderInfo->src;
	Rect* des = renderInfo->des;
	float alpha = renderInfo->alpha;
	float deep = renderInfo->deep;
	float angle = renderInfo->angle;

	verticesArray[0] = verticesArray[6]= des->x;
	verticesArray[3] = verticesArray[9] = des->x + des->width;
	verticesArray[1] = verticesArray[4] = des->y;
	verticesArray[7] = verticesArray[10] = des->y + des->height;
	verticesArray[2] = verticesArray[5] = verticesArray[8] = verticesArray[11] = deep;

	int imageWidth = texture->GetWidth();
	int imageHeight = texture->GetHeight();

	//Texture coordinate mapping from rect des
	float left = (float)src->x/imageWidth;
	float right = (float)(src->x+src->width)/imageWidth;
	float top = 1.0f - (float)src->y/imageHeight;
	float bottom = 1.0f - (float)(src->y+src->height)/imageHeight;

	texCoors[0] = texCoors[4] = left;
	texCoors[2] = texCoors[6] = right;
	texCoors[1] = texCoors[3] = top;
	texCoors[5] = texCoors[7] = bottom;

	glVertexPointer(3, GL_FLOAT, 0, verticesArray);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoors);
	glBindTexture(GL_TEXTURE_2D, texture->GetTexture());

	glColor4f(1.0f, 1.0f, 1.0f, alpha);
	
	glLoadIdentity();
	glTranslatef(des->x+des->width/2, des->y+des->height/2, 0);
	glRotatef(angle, 0.0f, 0.0f, 1.0f);
	glTranslatef(-(des->x+des->width/2), -(des->y+des->height/2), 0);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	
	glLoadIdentity();
	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}

bool CompareRenderInfo(RenderInfo* a, RenderInfo* b)
{
	if(a->deep < b->deep)
		return true;
	else return false;
}


void Graphics::RenderAll()
{
	//Draw all
	list<RenderInfo*>::iterator i;
	renderInfos.sort(CompareRenderInfo);
	for(i=renderInfos.begin(); i!=renderInfos.end(); i++)
	{
		RenderATexture(*i);
	}

	//Clear draw infos
	for(i=renderInfos.begin(); i!=renderInfos.end(); i++)
	{
		DELETE_SAFELY(*i);
	}
	renderInfos.clear();
}

void Graphics::Destroy()
{
	PRINT("Destroy Graphics\n");
}